#include "ghostskill.h"
#include "gametable.h"
#include "infoboard.h"
#include "player.h"
#include "playerskillobject.h"
#include "ghost.h"

GhostSkillFactory * GhostSkillFactory::_this = 0;

GhostSkillFactory::GhostSkillFactory(QObject *parent) :
    QObject(parent)
{
}

GhostSkillList * GhostSkillFactory
::
createGhostSkillList( GhostSkills skills, Ghost * ghost, GameTable * table )
{
    if( _this == 0 )
    {
        _this = new GhostSkillFactory;
    }
    GhostSkillList * res = new GhostSkillList( skills );
    // check all skills flags
    // add all possible skills flag handler here.
    // note that the skill check order matters when invoking them
    if( skills.testFlag( ONE_MORE_CARD ) )
    {
        GhostSkillObject * o = new OMC_GSkill( ghost, table );
        *res << o;
    }
    if( skills.testFlag( SEAL_SKILLS ) )
    {
        GhostSkillObject * o = new SEALS_GSkill( ghost, table );
        *res << o;
    }
    if( skills.testFlag( CURSE_DICE ) )
    {
        GhostSkillObject * o = new Curse_GSkill( ghost, table );
        *res << o;
    }
    if( skills.testFlag( LOSE_QI ) )
    {
        GhostSkillObject * o = new LQ_GSkill( ghost, table );
        *res << o;
    }
    if( skills.testFlag( LOSE_FABAO ) )
    {
        GhostSkillObject * o = new LF_GSkill( ghost, table );
        *res << o;
    }
    if( skills.testFlag( DICE_HOLDER ) )
    {
        GhostSkillObject * o = new DH_GSkill( ghost, table );
        *res << o;
    }

    if( skills.testFlag( QI ) )
    {
        GhostSkillObject * o = new QI_Reward( ghost, table );
        *res << o;
    }

    if( skills.testFlag( YINYANG ) )
    {
        GhostSkillObject * o = new YINYANG_Reward( ghost, table );
        *res << o;
    }

    if( res->size() > 0 )
    {
        GhostSkillObject * o = res->last();
        connect( o, SIGNAL(invoked()), res, SIGNAL(invoked_all()) );
    }
    return res;
}


GhostSkillList::GhostSkillList( GhostSkills s )
    :SKILLS( s )
{
}

void GhostSkillList::invoke_all()
{
    for( int i = 0; i < this->size(); i ++ )
    {
        this->at( i )->invoke();
    }
}
void GhostSkillList::exo_actions()
{
    for( int i = 0; i < this->size(); i ++ )
    {
        this->at( i )->exo_action();
    }
}

bool GhostSkillList::invokable()
{
    if( this->empty() )
        return false;
    for( int i = 0; i < this->size(); i ++ )
    {
        if( !this->at( i )->invokable() )
            return false;
    }
    return true;
}

bool OMC_GSkill::invokable()
{
    return !_table->getDeckBoard()->empty();
}

void OMC_GSkill::invoke()
{
    if( !invokable() )
        return;
    qDebug() << "Ghost Skill: one more card";
    _table->ghost_arrival();
}

void SEALS_GSkill::invoke()
{
    qDebug() << "Ghost Skill: Seal current player's skill";
    _target_board = _table->lastAllocatedGhost()->getGhostBoard();
    _target_board->sealSkill();
}
void SEALS_GSkill::exo_action()
{
    if(_seal_skills)
    {
        _target_board->releaseSkill();
    }
}
bool Curse_GSkill::invokable()
{
    // here it shall check the player's skill
    // whether he is immune to curse dice or not
    return true;
}

void Curse_GSkill::invoke()
{
    qDebug() << "Ghost Skill: the player rolls a curse dice";
    _table->roll_curse_dice();
}


void LQ_GSkill::invoke()
{
    qDebug() << "Ghost Skill: the player loses a Qi";
    int qi = _table->getCurrentPlayer()->getQi();
    _table->getCurrentPlayer()->setQi( qi - 1 );
}

void LF_GSkill::invoke()
{
    qDebug() << "Ghost Skill: the player loses all his fabao";
    _table->getCurrentPlayer()->resetAllResists();
    qDebug() << "";
}

void DH_GSkill::invoke()
{
    qDebug() << "Ghost Skill: this ghost holds one dice until exocised.";
    int n = _table->getItemManager()->getDiceNum();
    _table->getItemManager()->setDiceNum( n - 1 );
}
void DH_GSkill::exo_action()
{
    int n = _table->getItemManager()->getDiceNum();
    _table->getItemManager()->setDiceNum( n + 1 );
}

void QI_Reward::invoke()
{
    qDebug() << "Ghost Skill(reward): the player gets a bonus Qi";
    int qi = _table->getCurrentPlayer()->getQi();
    _table->getCurrentPlayer()->setQi( qi + 1 );
}

void YINYANG_Reward::invoke()
{
    qDebug() << "Ghost Skill(reward): the player renews his Yinyang";
    _table->getCurrentPlayer()->setYinyang( true );
}


